package jgf;

import java.io.Serializable;
import java.util.List;
import jgf.beans.ArcBean;
import jgf.beans.NodeBean;
import jgf.exceptions.arc.ArcException;
import jgf.exceptions.arc.DuplicatedArcException;
import jgf.exceptions.arc.UnexistentArcException;
import jgf.exceptions.attribute.AttributeException;
import jgf.exceptions.attribute.BadAttributeListException;
import jgf.exceptions.attribute.DuplicatedAttributeException;
import jgf.exceptions.attribute.UnexistentAttributeException;
import jgf.exceptions.node.DuplicatedNodeException;
import jgf.exceptions.node.UnexistentNodeException;

/**
 * 
 * @author Marcos Garcia Ortega <a href="mailto:thiamath@gmail.com">&lt;thiamath@gmail.com&gt;
 */
public interface IGraph extends Serializable {

	//////////////////////
	// Graph management //
	//////////////////////

	// <editor-fold defaultstate="collapsed" desc="Graph management">
	/**
	 * Returns the type of the graph as specified by the static constants.
	 * @return The type of the graph.
	 * @see <a href="../constant-values.html#jgs.IGraph" >Constant values</a>
	 */
	public int getType();

	/**
	 * Returns the identifier assigned to this graph.
	 * @return An Integer that (should) identify univocally this graph
	 *	in the graph pool.
	 */
	public Integer getID();

	/**
	 * Sets the identifier of the graph.
	 * @param id The new ID for the graph.
	 */
	public void setID(Integer id);

	/**
	 * Gets the name assigned to the graph.
	 * @return A String with the name of the graph.
	 */
	String getName();

	/**
	 * Sets the name of the graph.
	 * @param name A String with the new name of the graph.
	 */
	void setName(String name);
	// </editor-fold>

	//////////////////////
	// Nodes management //
	//////////////////////
	
	// <editor-fold defaultstate="collapsed" desc="Nodes management">
	/**
	 * Inserts a new node into the graph.
	 * @param label A String with a label to assign to the node.
	 * @return An Integer with the ID number of the node.
	 */
	public Integer insertNode(String label);

	/**
	 * Deletes the node identified by its ID number from the graph.
	 * @param nodeID An Integer with the ID number of the node to delete.
	 * @throws UnexistentNodeException If the given ID number
	 *		do not correspond to any node in the graph,
	 *		this exception will raise.
	 */
	public void deleteNode(Integer nodeID)
		throws UnexistentNodeException;

	/**
	 * Gets all the information related to a Node.
	 * @param nodeId An Integer with the ID number of the node.
	 * @return A NodeBean with all the relevant information of the node.
	 * @throws UnexistentNodeException If the given ID number
	 *		do not correspond to any node in the graph, this exception will raise.
	 */
	public NodeBean selectNode(Integer nodeId)
		throws UnexistentNodeException;

	/**
	 * Updates the node identified by its ID number with a new label
	 * and a new list of attributes.
	 * If one of the modifying parameters is null, then it will be kept as was.
	 * If both are null, then this function has no effect.
	 * @param nodeId An Integer with the ID number of the node.
	 * @param newLabel A String with the new label for the node, or null
	 *		to keep it "as is".
	 * @param newAttributes A List of Attribute with the new list of attributes.
	 *		It must have attributes that can be assignable to the nodes
	 *		(i.e. the node must have already attributes with the names
	 *		of the passed attributes). If is null, then no attributes
	 *		will change.
	 * @throws UnexistentNodeException If the graph does not have any node
	 *		with the passed ID, then this exception will raise.
	 * @throws BadAttributeListException If any of the attributes passed
	 *		to the method contains a name that cannot be assignable
	 *		to a node of this graph, then this exception will raise.
	 */
	public void updateNode(Integer nodeId, String newLabel, List<Attribute> newAttributes)
		throws UnexistentNodeException,
		BadAttributeListException;

	/**
	 * Adds a new attribute for the nodes. It will be implemented
	 * in all the nodes of the graph with the given default value.
	 * @param defaultValue The new default attribute.
	 * @throws DuplicatedAttributeException If the selected name
	 *		for the attribute is already present on the model,
	 *		this exception will raise.
	 */
	public void addDefaultNodeAttribute(Attribute defaultAttribute)
		throws DuplicatedAttributeException;

	/**
	 * Removes the attribute for all the nodes in the graph.
	 * @param name A String with the name of the attribute.
	 * @throws UnexistentAttributeException If the attribute does not exist
	 *		for nodes on this graph, this exception will raise.
	 */
	public void removeDefaultNodeAttribute(String name)
		throws UnexistentAttributeException;

	/**
	 * Changes the name of a node attribute to a new value and changes also
	 * its default value.
	 * @param previousName A String with the previous name of the attribute.
	 * @param newValue The new default values for the attribute.
	 * @throws AttributeException If any of the given attributes is null,
	 *		this exception will raise.
	 * @throws DuplicatedAttributeException If the new name already exists
	 *		on the list of default attributes for nodes,
	 *		this exception will raise.
	 * @throws UnexistentAttributeException If the previous name
	 *		does not exist on the list of default attributes for nodes,
	 *		this exception will raise.
	 */
	public void updateDefaultNodeAttribute(String previousName, Attribute newValue)
		throws AttributeException,
		DuplicatedAttributeException,
		UnexistentAttributeException;

	/**
	 * Gets a List with the attributes for nodes and its default values for the graph.
	 * @return A List of Attribute with the default attributes for nodes on the graph.
	 */
	public List<Attribute> getDefaultNodeAttributes();

	/**
	 * Checks if all the attributes in the list match with the attribute list
	 * assigned to the nodes.
	 * @param attributes A List of Attribute with the attributes to validate.
	 * @return True if all the attributes match or false otherwise.
	 */
	public boolean validateNodeAttributeList(List<Attribute> attributes);

	/**
	 * Get the list of attributes for the given node.
	 * @param nodeId An Integer with the ID number of the node to consult
	 *		the attributes.
	 * @return A List<Attribute> with the attributes assigned to the node
	 *		designed by nodeId.
	 * @throws UnexistentNodeException If the indicated node doesn't exist,
	 *		this exception will raise.
	 */
	public List<Attribute> getNodeAttributes(Integer nodeId)
		throws UnexistentNodeException;

	/**
	 * Gets a list with the ID numbers of all the nodes on this graph.
	 * @return List of Integer with all the ID numbers of the nodes present
	 *		on this graph.
	 */
	public List<Integer> getNodeList();

	/**
	 * Gets the ID number of the node that acts as source in this graph
	 * if any or null if theres no source.
	 * @return A List of Integer with the ID numbers of all the source nodes
	 *		(may be empty if theres no source checked).
	 */
	public List<Integer> getSources();

	/**
	 * Sets the node of the graph by its ID number to the state of source.
	 * @param nodeId An Integer with the ID number of the node.
	 * @throws DuplicatedNodeException If the node to insert into the sources
	 *		is already there, then this exception will raise.
	 * @throws UnexistentNodeException If the node to insert into the sources
	 *		do not exist, then this exception will raise.
	 */
	public void setSource(Integer nodeId)
		throws DuplicatedNodeException,
		UnexistentNodeException;

	/**
	 * Usets the state of source to the node identified by its ID number.
	 * @param nodeId An Integer with the ID number of the node.
	 * @throws UnexistentNodeException If the node to remove from the sources
	 *		is not there, then this exception will raise.
	 */
	public void unsetSource(Integer nodeId)
		throws UnexistentNodeException;

	/**
	 * Gets the ID number of the node that acts as sink in this graph if any
	 * or null if theres no sink.
	 * @return A List of Integer with the ID numbers of all the sink nodes
	 *		(may be empty if theres no sink checked).
	 */
	public List<Integer> getSinks();

	/**
	 * Sets the node of the graph by its ID number to the state of sink.
	 * @param nodeId An Integer with the ID number of the node.
	 * @throws DuplicatedNodeException If the node to insert into the sinks
	 *		is already there, then this exception will raise.
	 * @throws UnexistentNodeException If the node to insert into the sinks
	 *		do not exist, then this exception will raise.
	 */
	public void setSink(Integer nodeId)
		throws DuplicatedNodeException,
		UnexistentNodeException;

	/**
	 * Usets the state of sink to the node identified by its ID number.
	 * @param nodeId An Integer with the ID number of the node.
	 * @throws UnexistentNodeException If the node to remove from the sinks
	 *		is not there, then this exception will raise.
	 */
	public void unsetSink(Integer nodeId)
		throws UnexistentNodeException;
	// </editor-fold>

	/////////////////////
	// Arcs management //
	/////////////////////

	// <editor-fold defaultstate="collapsed" desc="Arcs management">
	/**
	 * Inserts a new arc into the graph.
	 * @param from The ID number of the node from where the arc leaves.
	 * @param to The ID number of the node where the arc arrives.
	 * @param label A String with the label selected for the arc.
	 * @return Returns an Integer with the ID number for the arc.
	 * @throws ArcException If there is an generic problem, as null pointers
	 *		etc. this exception will raise.
	 * @throws DuplicatedArcException If you try to insert an arc between
	 *		two nodes that have already an arc and the graph is not multiple,
	 *		this exception will raise.
	 * @throws DuplicatedNodeException If you try to insert an arc that
	 *		have the same node as 'from' and 'to' and the graph is not
	 *		a pseudograph, this exception will raise.
	 * @throws UnexistentNodeException If one of the given nodes to define
	 *		the arc do not exist on the graph, this exception will raise.
	 */
	public Integer insertArc(Integer from, Integer to, String label)
		throws ArcException,
		DuplicatedArcException,
		DuplicatedNodeException,
		UnexistentNodeException;

	/**
	 * Removes the arc identified by its ID number from the graph.
	 * @param arcId An Integer with the ID number of the arc to delete.
	 * @throws UnexistentArcException If the given ID number is not mapped
	 *		in the arc tree, this exception will raise.
	 */
	public void deleteArc(Integer arcId)
			throws UnexistentArcException;

	/**
	 * Gets the information from an arc selecting it with its ID number.
	 * @param arcId An Integer with the ID number of the arc.
	 * @return An ArcBean with all the information of the arc.
	 * @throws UnexistentArcException If the given ID number is not mapped
	 *		in the arc tree, this exception will raise.
	 */
	public ArcBean selectArc(Integer arcId)
			throws UnexistentArcException;

	/**
	 * Updates the arc identified by its ID number with a new label
	 * and a new list of attributes.
	 * If one of the modifying parameters is null, then it will be kept as was.
	 * If both are null, then this function has no effect.
	 * @param arcId The ID number of the arc to update.
	 * @param newLabel A String with the new label of the arc or null.
	 * @param newAttributes A List of Attribute with the new attributes
	 *		for the arc. Is not mandatory to send all the attributes
	 *		assigned to arcs. Only the sended will be updated.
	 *		But all the sended attributes must be assigned to arcs.
	 * @throws UnexistentArcException If the given ID number do not correspond
	 *		with any arc in the graph, this exception will raise.
	 * @throws BadAttributeListException If any of the given attributes
	 *		do not match with the attributes assigned to arcs on the graph,
	 *		this exception will raise.
	 */
	public void updateArc(Integer arcId, String newLabel, List<Attribute> newAttributes)
		throws UnexistentArcException,
		BadAttributeListException;

	/**
	 * Gets the forward star of the node. A forward star means all the arcs
	 * that leave from that node to others.
	 * In non directed graphs its the same that the star.
	 * @param nodeID An Integer with the ID number of the node.
	 * @return A List of Integer containing the ID numbers of the arcs
	 *		in the forward star of the given node.
	 */
	public List<Integer> getForwardStar(Integer nodeID);

	/**
	 * Gets the backward star of the node. A backward star means all the arcs
	 * that come into that node from others.
	 * In non directed graphs its the same that the star.
	 * @param nodeID An Integer with the ID number of the node.
	 * @return A List of Integer containing the ID numbers of the arcs
	 *		in the backward star of the given node.
	 */
	public List<Integer> getBackwardStar(Integer nodeID);

	/**
	 * Gets the star of the node. A star means all the arcs linked to the node.
	 * @param nodeID An Integer with the ID number of the node.
	 * @return A List of Integer containing the ID numbers of the arcs
	 *		in the star of the given node.
	 */
	public List<Integer> getStar(Integer nodeID);

	/**
	 * Gets all the arcs in the graph.
	 * @return A List of Integer with all the ID numbers of the arcs
	 *		in the graph.
	 */
	public List<Integer> getArcList();

	/**
	 * Gets all the arcs that are between the same two nodes.
	 * In non multiple graphs, this function will return always only one node
	 * in the list.
	 * If the graph is directed, then the way of the arc will be taken
	 * into account when populate the list.
	 * @param nodeFromID The node from where the arcs leaves.
	 * @param nodeToID The node where the arcs arrives to.
	 * @return A List of Integer with all the arcs that are between
	 *		the "from" and "to" nodes.
	 * @throws UnexistentArcException If the from and to nodes
	 *		do not have any arc, this exception will raise.
	 */
	public List<Integer> getMultiarcList(Integer nodeFromID, Integer nodeToID)
			throws UnexistentArcException;
	/**
	 * Gets all the attributes of an arc.
	 * @param arcID The ID number of the arc.
	 * @return A List of Attribute that returns all the attributes of the arc.
	 */
	public List<Attribute> getArcAttributes(Integer arcID);

	/**
	 * Adds a new attribute for the arcs. It will be implemented in all
	 * the arcs of the graph with the given default value.
	 * @param defaultAttribute The new default attribute.
	 * @throws DuplicatedAttributeException If the selected name
	 *		for the attribute is already present on the model,
	 *		this exception will raise.
	 */
	public void addDefaultArcAttribute(Attribute defaultAttribute)
			throws DuplicatedAttributeException;

	/**
	 * Removes the attribute for all the arcs in the graph.
	 * @param attributeName A String with the name of the attribute.
	 * @throws UnexistentAttributeException If the attribute does not exist
	 *		for nodes on this graph, this exception will raise.
	 */
	public void removeDefaultArcAttribute(String name)
			throws UnexistentAttributeException;

	/**
	 * Changes the name of an arc attribute to a new name and changes also
	 * its default value.
	 * @param previousName A String with the previous name of the attribute.
	 * @param newValue The new default values for the attribute.
	 * @throws AttributeException If any of the given attributes is null,
	 *		this exception will raise.
	 * @throws DuplicatedAttributeException If the new name already exists on
	 *		the list of default attributes for nodes, this exception will raise.
	 * @throws UnexistentAttributeException If the previous name does not exist 
	 *		on the list of default attributes for nodes, this exception
	 *		will raise.
	 */
	public void updateDefaultArcAttribute(String previousName, Attribute newValue)
		throws AttributeException,
		DuplicatedAttributeException,
		UnexistentAttributeException ;

	/**
	 * Gets a List with the attributes for arcs and its default
	 * values for the graph.
	 * @return A List of Attribute with the default attributes for arcs
	 *		on the graph.
	 */
	public List<Attribute> getDefaultArcAttributes();

	/**
	 * Checks if all the attributes in the list match with the attribute list
	 * assigned to the arcs.
	 * @param attributes A List of Attribute with the attributes to validate.
	 * @return True if all the attributes match or false otherwise.
	 */
	public boolean validateArcAttributeList(List<Attribute> attributes);
	// </editor-fold>

	///////////////
	// Constants //
	///////////////

	// <editor-fold defaultstate="collapsed" desc="Constants">
	/** Indicate digraph type. */
	public static final int GRAPH = 0;
	/** Indicate simple graph type. */
	public static final int DIGRAPH = 1;
	/** Indicate multigraph type. */
	public static final int MULTI = 2;
	/** Indicate pseudo type. */
	public static final int PSEUDO = 4;
	// </editor-fold>

}
